
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections.Generic;
using System.Text;

using Swaf;
using Swaf.BizObj;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;

namespace Swaf.Compression
{
    [Serializable]
    public class CompressionBizObjDecorator : GenericDecorator, IBizObjDecorator
    {
        #region Properties

        private Boolean _isActive;

        public Boolean IsActive
        {
            get { return _isActive; }
            set { _isActive = value; }
        }

        public ICompressionManager CompressionMgr
        {
            get { return Application.currentApp.appData["sysObjs-Compression"] as ICompressionManager; }
        }

        #endregion

        #region Constructors

        public CompressionBizObjDecorator(string name, string val, object otherInfo)
            : base(name, val, otherInfo)
        {
            IBizObjField field = otherInfo as IBizObjField;
            Debug.Assert(field != null);

            try
            {
                IsActive = Convert.ToBoolean(m_val);
            }
            catch (Exception e)
            {
                throw new CompressionException(
                    String.Format("Invalid value '{0}' specified for compression bizobj field decorator.  Valid values include 'true' or 'false'",
                    val), e);
            }

            // Regardless of what the compress decorator specifies, if the decorator
            // is placed on a Method rather than a Field, we are going to ignore it.
            if (field.BizType == BizFieldType.Method)
            {
                IsActive = false;
            }
        }
        #endregion

        #region IBizObjDecorator Members

        public void put(IBizObj parent, IBizObjField field, ref object val, object extraInfo, ref bool shouldBeFieldType)
        {
            // Only operate on a populated field, if the decorator is active
            if (val == null || !IsActive)
            {
                return;
            }

            // Assume value with be a field type
            shouldBeFieldType = false;

            // Package value into a Stream to enable compression
            using (MemoryStream ms = new MemoryStream())
            {
                new BinaryFormatter().Serialize(ms, val);

                ms.Position = 0L;

                // Compress the value
                val = CompressionMgr.Compress(ms);
            }
        }

        public void get(IBizObj parent, IBizObjField field, ref object val, object[] extraInfo, ref bool shouldBeFieldType)
        {
            // Only operate on a populated field, if the decorator is active
            if (val == null || !IsActive)
            {
                return;
            }

            // Assume value with be a field type
            shouldBeFieldType = true;

            using (MemoryStream ms = new MemoryStream())
            {
                // Decompress the data into the ms
                CompressionMgr.Decompress(val as String, ms);

                // Reposition to the beginning of the stream
                ms.Position = 0L;

                // Deserialize the object
                val = new BinaryFormatter().Deserialize(ms);
            }
        }

        public bool doesUseFullXmlElement()
        {
            return false;
        }

        #endregion

        public override bool IsStandin
        {
            get
            {
                return true;
            }
        }
    }
}
